<?php

namespace app\common\model\xilumarket;

use think\Db;
use think\Model;
use think\Exception;
use think\db\Expression;
use app\common\model\User;
use function fast\array_get;
use traits\model\SoftDelete;
use app\common\model\DeliveryKey;
use think\exception\PDOException;


class Product extends Model
{

    use SoftDelete;

    

    // 表名
    protected $name = 'xilumarket_product';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'integer';

    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = 'deletetime';

    // 追加属性
    protected $append = [
        'status_text',
        'thumb_image_text',
    ];

    protected $type = [
        'freight_status'    => 'json',
    ];

    public static function init()
    {
        self::beforeInsert(function ($row){
            #获取经纬度
            if($row['product_type'] == 1 && $row['province_id'] && $row['city_id'] && $row['region_id'] && $row['address']){
                $province  = Area::getNameById($row['province_id']);
                $city  = Area::getNameById($row['city_id']);
                $region  = Area::getNameById($row['region_id']);

                $geo = xilumarketGetGeo($province.$city.$region.$row['address']);
                if($geo['status']){
                    $row['lat']  = $geo['lat'];
                    $row['lng']  = $geo['lng'];
                }
                return $row;
            }
        });
    }

    public function getStatusList()
    {
        return ['0' => __('Status 0'), '1' => __('Status 1')];
    }

    public function getCreatetimeTextAttr($value,$data){
        if(isset($data['createtime'])){
            return datetime($data['createtime'],'Y-m-d H:i');
        }
        return '';
    }

    public function getThumbImageTextAttr($value,$data){
        return $value ? cdnurl($value,true) : (isset($data['thumb_image'])?cdnurl($data['thumb_image'],true):"");
    }

    public function getImagesTextAttr($value,$data){
        $images = [];
        $value = isset($data['images'])?$data['images']:'';
        if($value && is_string($value)){
            $images_array = explode(',',$value);
            foreach ($images_array as $image){
                $images[] = cdnurl($image,true);
            }
        }
        return $images;
    }

    public function getStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['status']) ? $data['status'] : '');
        $list = $this->getStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    public function user(){
        return $this->belongsTo(\app\common\model\xilumarket\User::class,'user_id','id',[],'inner')->setEagerlyType(0);
    }

    public static function getMyProductCount($where,$user_id){
        $where['user_id'] = $user_id;
        return self::where($where)
            ->order('weigh','desc')
            ->count(1);
    }

    /**
     * 添加闲置
     */
    public static function add($params,$userId){
        $validate = new \app\common\validate\xilumarket\Product();
        if(!$validate->check($params)){
            throw new Exception($validate->getError());
        }
        $params['user_id'] = $userId;
        $params['thumb_image'] = explode(',',$params['images'])[0];
        if($id = array_get($params,'id')){
            $model = self::get($id);
        }else{
            $model = new self;
        }
        //判断是否需要审核
        $shopinfo = Config::getMyConfig('shopinfo');
        $params['check_status'] = 1;
        $params['refuse_reason'] = '';
        if($shopinfo && $shopinfo['product_check_switch'] == 0){
            $params['check_status'] = 2;
        }
        check_sens_word(array_get($params, 'name'));
        check_sens_word(array_get($params, 'content'));
        $result = $model->save(array_intersect_key($params, array_flip((array) [
            'product_type','user_id','province_id','city_id','region_id','address','category_id','check_status',
            'thumb_image' ,'images','name', 'content', 'salesprice','line_price', 'freight_status','freight_money', 'number'
        ])));
        //如果包含自提，则添加至骑手关键词表中
        if(in_array(4, $params['freight_status'])){
            $keys = DeliveryKey::where([
                'province_id'=>$params['province_id'],
                'city_id'=>$params['city_id'],
                'region_id'=>$params['region_id'], 
                'status' => 1
            ])->page(1, 5)->select();
            foreach($keys as $key) {
                $ids = $key->product_ids;
                if($ids == null){
                    $ids = [];
                }
                if(strpos($params['address'], $key->key) !== false){
                    array_push($ids, $model->id);
                }
                $key->save(['product_ids' => $ids]);
            }
        }
        if($result === false){
            throw new Exception($model->getError());
        }
        return $model;
    }

    /**
     * 添加回收
     */
    public static function recovery($params,$userId){
        $validate = new \app\common\validate\xilumarket\Product();
        if(!$validate->scene('edit')->check($params)){
            throw new Exception($validate->getError());
        }
        $params['user_id'] = $userId;
        $params['thumb_image'] = explode(',',$params['images'])[0];
        if($id = array_get($params,'id')){
            $model = self::get($id);
        }else{
            $model = new self;
        }
        //判断是否需要审核
        $shopinfo = Config::getMyConfig('shopinfo');
        if($shopinfo && $shopinfo['recovery_check_switch'] == 0){
            $params['check_status'] = 2;
        }
        Db::startTrans();
        try {
            $result = $model->save(array_intersect_key($params, array_flip((array) [
                'product_type','user_id','category_id','check_status','thumb_image' ,'images','name', 'content',
                'salesprice', 'freight_status','freight_money'
            ])));
            //城市
            ProductCity::add($model,array_get($params,'areas_ids'));
        }catch (Exception $e){
            Db::rollback();
            throw $e;
        }
        Db::commit();
        return $model;
    }

    /**
     * 闲置列表
     * @param $params
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public static function lists($params,$userId){
        $pagesize = array_get($params,'pagesize',10);

        $where['product.product_type'] = '1';
        $where['product.status'] = '2';
        $where['product.sale_out_status'] = '0';
        $where['product.check_status'] = '2';
        if($category_id = array_get($params,'category_id')){
            if($category_id == -1){
                //猜你喜欢
                $product_id = $userId?FooterView::where('user_id',$userId)->where(FooterView::TYPE_PRODUCT)->column("footer_id"):[];
                $category_id = $product_id?self::whereIn('id',$product_id)->group('category_id')->column('category_id'):[];
                if($category_id){
                    $where['product.category_id'] = ['in',$category_id];
                }
            }else{
                $child_ids = ProductCategory::where('pid',$category_id)->column('id')?:[];
                array_push($child_ids,$category_id);
                $where['product.category_id'] = ['in',$child_ids];
            }
        }
        if($city_id = array_get($params,'city_id')){
            $where['city_id'] = $city_id;
        }else{
            $where['city_id'] = '-1';
        }
        $sort = array_get($params,'sort');
        switch ($sort){
            case 1:
                #最新发布
                $order = "product.createtime desc";
                break;
            case 2:
                #距离最近
                $order = "distance asc";
                break;
            default:
                $order = "weigh desc";
        }
        if($q = array_get($params,'q')){
            $where['product.name'] = ['like',"%$q%"];
        }
        if(isset($params['lng']) && $params['lat']){
            $field = "id,name,thumb_image,want_num,salesprice,freight_status,(ST_DISTANCE(POINT(".$params['lng'].", ".$params['lat']."), POINT(lng, lat)) * 111195) AS distance";
        }else{
            $field = "id,name,thumb_image,want_num,salesprice,freight_status";
        }
        $lists = self::field($field)
            ->with(['user'=>function($query){
            $query->withField(['id','nickname','username','avatar','mobile','logintime']);
        }])
            ->where($where)
            ->order($order)
            ->paginate($pagesize);

        return $lists;
    }

    /**
     * 回收列表
     * @param $params
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public static function recoveryLists($params,$userId){
        $pagesize = array_get($params,'pagesize',10);
        $where['product.status'] = '2';
        $where['product.check_status'] = '2';
        if($category_id = array_get($params,'category_id')){
            $where['product.category_id'] = $category_id;
        }
        if($q = array_get($params,'q')){
            $where['product.name'] = ['like',"%$q%"];
        }
        if($city_id = array_get($params,'city_id')){
            $product_ids = ProductCity::where('city_id',$city_id)->whereOr('city_id',0)->group('product_id')->column('product_id')?:[0];
            $where['product.id'] = ['in',$product_ids];
        }
        $lists = self::field("id,name,thumb_image,want_num,salesprice,freight_status")
            ->with(['user'=>function($query){
                $query->withField(['id','nickname','username','avatar','mobile','logintime']);
            }])
            ->where('product_type',2)
            ->where($where)
            ->order('weigh','desc')
            ->paginate($pagesize);
        return $lists;
    }

    /**
     * 我的闲置
     * @param $params
     * @param $user_id
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public static function mylists($params,$user_id){
        $pagesize = array_get($params,'pagesize',10);
        $where['product_type'] = 1;
        $where['user_id'] = $user_id;
        $state = array_get($params,'state');
        if($state == 0){
            //再售
            $where['status'] = 2;
            $where['check_status'] = 2;
            $where['sale_out_status'] = 0;
        }else if($state==1){
            //待审核
            $where['check_status'] = 1;
        }else if($state == 2){
            //未通过
            $where['check_status'] = 3;
        }else if($state == 3){
            //下架
            $where['check_status'] = 2;
            $where['status'] = 0;
        }else if($state == 4){
            //已售出
            $where['check_status'] = 2;
            $where['sale_out_status'] = 2;
        }
        $lists = self::field("id,category_id,user_id,province_id,city_id,region_id,address,scan_num,name,thumb_image,images,content,want_num,salesprice,line_price,status,check_status,refuse_reason,sale_out_status,freight_status,freight_money,createtime")
//            ->with(['user'=>function($query){
//                $query->withField(['id','nickname','username','avatar','mobile']);
//            }])
            ->where($where)
            ->order('weigh','desc')
            ->paginate($pagesize)
            ->each(function ($row){
                $row->append(['images_text']);
            });
        return $lists;
    }

    /**
     * 我的回收列表
     * @param $params
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public static function myRecoveryLists($params,$userId){
        $pagesize = array_get($params,'pagesize',10);
        $where['product_type'] = 2;
        $where['user_id'] = $userId;
        $state = array_get($params,'state');
        if($state == 0){
            //再售
            $where['status'] = 2;
        }else if($state == 1){
            $where['status'] = 0;
        }
        $lists = self::field("id,category_id,user_id,scan_num,name,thumb_image,images,content,want_num,salesprice,status,freight_status,freight_money,createtime")
//            ->with(['user'=>function($query){
//                $query->withField(['id','nickname','username','avatar','mobile']);
//            }])
            ->where($where)
            ->order('weigh','desc')
            ->paginate($pagesize)
            ->each(function ($row){
                $row->append(['images_text']);
                $row->city_ids = ProductCity::where('product_id',$row->id)->column('city_id');
            });
        return $lists;
    }


    /**
     * 主页-宝贝
     * @param $params
     * @param $user_id
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public static function homeLists($params,$user_id){
        $pagesize = array_get($params,'pagesize',10);
        $where['user_id'] = $user_id;
        $where['product_type'] = '1';
        $where['status'] = '2';
        $where['check_status'] = '2';
        $lists = self::field("id,category_id,user_id,scan_num,name,thumb_image,images,content,want_num,salesprice,status,freight_status,sale_out_status,freight_money,createtime")
            ->where($where)
            ->order('weigh','desc')
            ->paginate($pagesize);
        return $lists;
    }

    /**
     * @param $product_id
     * @return array|bool|false|\PDOStatement|string|Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function detail($product_id){
        $where['product.status'] = '2';
        $where['product.check_status'] = '2';
        $where['product.id'] = $product_id;
        $row = self::field("id,product_type,category_id,user_id,province_id,city_id,region_id,address,name,thumb_image,images,content,want_num,salesprice,line_price,freight_status,freight_money,createtime,sale_out_status")
            ->with(['user'=>function($query){
                $query->withField(['id','nickname','username','avatar','mobile','createtime','logintime']);
            }])
            ->where($where)
            ->find();

        $row && $row->append(['images_text','createtime_text']);
        return $row;
    }

    /**
     * 删除
     * @param $params
     * @param $user_id
     * @return bool
     * @throws Exception
     * @throws \think\exception\DbException
     */
    public static function del($params,$user_id){
        if(!$product_id = array_get($params,'product_id')){
            throw new Exception("商品参数错误");
        }
        $row = self::get($product_id);
        if(!$row){
            throw new Exception("商品不存在");
        }
        if($row->user_id != $user_id){
            throw new Exception("无权操作");
        }
        $row->delete();
        return true;
    }

    /**
     * 上下架
     */

    public static function multiStatus($params,$userId){
        $productId = array_get($params,'product_id');
        $row = $productId?self::get(['id'=>$productId,'user_id'=>$userId]):null;
        if(!$row){
            throw new Exception("商品不存在");
        }
        $status = array_get($params,'status');
        if(!in_array($status,[0,2])){
            throw new Exception("商品状态不存在");
        }
        $row->status = $status;
        $row->allowField(['status'])->save();
        return $row;
    }

    /**
     * 修改价格
     */
    public static function changePrice($params,$userId){
        $productId = array_get($params,'product_id');
        $row = $productId?self::get(['id'=>$productId,'user_id'=>$userId]):null;
        if(!$row){
            throw new Exception("商品不存在");
        }
        $salesprice = array_get($params,'salesprice');
        if(!$salesprice){
            throw new Exception("修改价格错误");
        }
        if($salesprice>=$row->salesprice){
            throw new Exception("降价高于售价");
        }
        Db::startTrans();
        try {
            $row->salesprice = new Expression("salesprice-".$salesprice);
            $row->allowField(['salesprice'])->save();
            #todo 修改记录
            ProductReduce::create([
                "user_id"=>$row->user_id,
                "product_id"=>$row->id,
                'price'=>$salesprice
            ]);
        }catch (Exception|PDOException $e){
            Db::rollback();
            throw $e;
        }
        Db::commit();
        return self::get($row->id);
    }

    /**
     * @param $ids
     * @return bool|false|\PDOStatement|string|\think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function getProduct($ids){
        // field("id,user_id,name,thumb_image,category_id,check_status,freight_status,freight_money,sale_out_status,salesprice,line_price,sale_out_status")
        //     ->
        return self::whereIn('id',$ids)
            ->select();

    }
}
